package com.yunhe.authority.service.base.impl;

import com.yunhe.authority.service.authority.FirmService;
import com.yunhe.authority.service.base.AreaService;
import com.yunhe.common.model.PageParam;
import com.yunhe.authority.domain.base.Area;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.authority.repository.base.AreaRepository;
import com.yunhe.common.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 地区Service
 * @desc 地区服务类实现
 * @author liuronglei
 */
@Service
public class AreaServiceImpl implements AreaService {
    @Autowired
    AreaRepository areaRepository;
    @Autowired
    FirmService firmService;


    /**
     * 地区处理和判断
     * @param area 地区对象
     */
    private void processBeforeSave(Area area)
            throws ArgumentErrorException, UniqueConstraintsException {
        //判断地区编号是否为空
        if (StringUtil.isEmpty(area.getName())
                || area.getCode() == null
                || StringUtil.isEmpty(area.getTitle())) {
            throw new ArgumentErrorException("地区代码、地区编号、地区标题不能为空");
        }
        //判断地区编号是否已存在
        Area areaByName = this.findByName(area.getName());
        if (areaByName != null) {
            if (area.getId() == null || areaByName.getId().longValue() != area.getId().longValue()) {
                throw new UniqueConstraintsException("该地区编号已存在");
            }
        }
        //判断地区代码是否已存在
        Area areaByCode = this.findByCode(area.getCode());
        if (areaByCode != null) {
            if (area.getId() == null || areaByCode.getId().longValue() != area.getId().longValue()) {
                throw new UniqueConstraintsException("该地区代码已存在");
            }
        }
    }

    /**
     * 移除重复的孩子地区
     * @param list 地区列表
     */
    private void removeRepeatChild(List<Area> list) {
        if (list != null && list.size() > 0) {
            //保存重复的ID
            Map<Long, Object> repeatIdMap = new HashMap<>();
            //第一次循环，获得所有孩子节点ID
            for (Area area : list) {
                List<Area> children =  area.getChildren();
                if (children != null && children.size() > 0) {
                    for (Area child: children) {
                        repeatIdMap.put(child.getId(), null);
                    }
                }
            }
            //根据是否是孩子节点移除元素
            for (int i = list.size() - 1; i >= 0; i--) {
                Area area = list.get(i);
                if (repeatIdMap.containsKey(area.getId())) {
                    list.remove(i);
                }
            }
        }
    }

    /**
     * 更新父地区关系（添加到父地区）
     * @param area 子地区对象
     * @param parentId 父地区ID
     */
    private void updateParent(Area area, Long parentId) throws ObjectNotFoundException {
        if (area != null) {
            areaRepository.unbindParentAreaById(area.getId());
        }
        if (parentId != null && parentId != -1) {
            Area parentArea = findByAreaId(parentId);
            if (parentArea == null) {
                throw new ObjectNotFoundException("找不到ID为" + parentId + "的父地区");
            }
            areaRepository.bindChildAreaById(parentId, area.getId());
        }
    }

    /**
     * 新增地区
     * @param area 新增对象
     */
    @Override
    @Transactional
    public Area createArea(Area area, Long parentId)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException {
        area.setId(null);
        processBeforeSave(area);
        Area newArea = areaRepository.save(area);
        //绑定父地区关系
        if (parentId != null) {
            updateParent(newArea, parentId);
        }
        return newArea;
    }

    /**
     * 批量新增地区
     * @param list 地区列表
     */
    @Override
    @Transactional
    public Iterable<Area> createArea(List<Area> list)
            throws ArgumentErrorException, UniqueConstraintsException {
        for (Area area : list) {
            area.setId(null);
            processBeforeSave(area);
        }
        return areaRepository.saveAll(list);
    }

    /**
     * 根据id删除地区
     * @param areaId id
     */
    @Override
    @Transactional
    public void deleteArea(Long areaId) {
        areaRepository.deleteById(areaId);
    }

    /**
     * 根据地区代码删除地区
     * @param code 地区代码
     */
    @Override
    @Transactional
    public Long deleteAreaByCode(Long code) {
        return areaRepository.deleteByCode(code);
    }

    /**
     * 根据地区编号删除地区
     * @param name 地区编号
     */
    @Override
    @Transactional
    public Long deleteAreaByName(String name) {
        return areaRepository.deleteByName(name);
    }

    /**
     * 更新地区（更新全部字段）
     * @param area 要更新的地区对象
     */
    @Override
    @Transactional
    public Area updateArea(Area area)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException {
        boolean exists = area.getId() != null && areaRepository.existsById(area.getId());
        if (!exists) {
            throw new ObjectNotFoundException("找不到ID为" + area.getId() + "的地区");
        }
        processBeforeSave(area);
        return areaRepository.save(area);
    }

    /**
     * 更新地区（更新指定字段）
     * @param areaId id
     * @param code 地区代码
     * @param name 地区编号
     * @param title 地区标题
     * @param adminArea 行政区
     */
    @Override
    public Area updateArea(Long areaId,
                           Long code,
                           String name,
                           String title,
                           String adminArea,
                           Long parentId)
            throws ArgumentErrorException, ObjectNotFoundException, UniqueConstraintsException {
        Area area = this.findByAreaId(areaId);
        if (area == null) {
            throw new ObjectNotFoundException("找不到ID为" + area.getId() + "的地区");
        }
        Optional.ofNullable(code).ifPresent(area::setCode);
        Optional.ofNullable(name).ifPresent(area::setName);
        Optional.ofNullable(title).ifPresent(area::setTitle);
        Optional.ofNullable(adminArea).ifPresent(area::setAdminArea);
        processBeforeSave(area);
        if (parentId != null) {
            updateParent(area, parentId);
        }
        return areaRepository.save(area);
    }

    /**
     * 根据ID获得地区对象
     * @param id id
     */
    @Override
    public Area findByAreaId(Long id) {
        return areaRepository.findById(id).orElse(null);
    }

    /**
     * 根据地区代码获得地区对象
     * @param code 地区代码
     */
    @Override
    public Area findByCode(Long code) {
        return areaRepository.findByCode(code);
    }

    /**
     * 根据地区编号获得地区对象
     * @param name 地区编号
     */
    @Override
    public Area findByName(String name) {
        return areaRepository.findByName(name);
    }

    /**
     * 根据地区标题获得地区对象
     * @param title 地区标题
     */
    @Override
    public Area findByTitle(String title) {
        return areaRepository.findByTitle(title);
    }

    /**
     * 获得有单位关联的地区对象
     */
    @Override
    public Iterable<Area> findFirmAreas() {
        return areaRepository.findFirmAreas();
    }

    /**
     * 根据单位代码获得单位关联的地区对象
     * @param firmCode 单位代码
     */
    @Override
    public Area findFirmArea(Long firmCode) {
        return areaRepository.findFirmArea(firmCode);
    }

    /**
     * 获得所有地区对象
     * @param pageParam 分页对象
     */
    @Override
    public Iterable<Area> findAreas(PageParam pageParam) {
        //Iterable<Area> results;
//        if (QueryUtil.needPaging(pageParam)) {
//            results = areaRepository.findAll(QueryUtil.getPageRequest(pageParam));
//        } else {
//            Sort sort = pageParam == null ? null : QueryUtil.getSort(pageParam.getSort());
//            if (sort != null) {
//                results = areaRepository.findAll(sort);
//            } else {
//                results = areaRepository.findAll();
//            }
//        }
        List<Area> results = (List<Area>)areaRepository.findAreas();
        removeRepeatChild(results);
        return results;
    }

    /**
     *根据单位获取所属地区
     */
    @Override
    public Iterable<Area> findAreaByFirmId(Long firmId){
        return areaRepository.findAreaByFirmId(firmId);
    }

    @Override
    public Area findByStationCode(Long stationCode) {
        return areaRepository.findByStationCode(stationCode);
    }
}
